package com.ruoyi.system.service.impl;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.domain.SysStudentBenefit;
import com.ruoyi.system.domain.SysStudentBenefitExchange;
import com.ruoyi.system.domain.SysStudentRank;
import com.ruoyi.system.domain.SysStudentRankHistory;
import com.ruoyi.system.mapper.SysStudentBenefitExchangeMapper;
import com.ruoyi.system.mapper.SysStudentBenefitMapper;
import com.ruoyi.system.mapper.SysStudentRankHistoryMapper;
import com.ruoyi.system.mapper.SysStudentRankMapper;
import com.ruoyi.system.service.SysStudentBenefitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class SysStudentBenefitServiceImpl implements SysStudentBenefitService {

    @Resource
    private SysStudentBenefitMapper benefitMapper;

    @Autowired
    private SysStudentRankMapper rankMapper;

    @Resource
    private SysStudentBenefitExchangeMapper exchangeMapper;

    @Autowired
    private SysStudentRankHistoryMapper sysStudentRankHistoryMapper;

    // 总段位顺序（从低到高）
    private static final List<String> RANK_LEVEL_ORDER = new ArrayList<String>() {{
        add("倔强青铜");  // 索引0（最低段位）
        add("秩序白银");  // 索引1
        add("荣耀黄金");  // 索引2
        add("尊贵铂金");  // 索引3
        add("永恒钻石");  // 索引4
        add("至尊星耀");  // 索引5
        add("最强王者");  // 索引6（最高段位）
    }};

    // 小段位顺序（从高到低：I→V）
    private static final List<String> RANK_SUB_LEVEL_ORDER = new ArrayList<String>() {{
        add("I");
        add("II");
        add("III");
        add("IV");
        add("V");
    }};

    // 每降1个小段位补充的经验值
    private static final int EXP_PER_SUB_DOWNGRADE = 1200;

    // 最低总段位标识
    private static final String LOWEST_RANK_LEVEL = "倔强青铜";


    /**
     * 获取所有启用的权益
     */
    @Override
    public List<SysStudentBenefit> getEnableBenefits() {
        List<SysStudentBenefit> benefits = benefitMapper.selectEnableBenefits();
        return benefits != null ? benefits : new ArrayList<>();
    }


    /**
     * 权益兑换核心方法（包含段位历史记录和统计同步）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean exchangeBenefit(Long userId, Long benefitId, Boolean needDowngrade) {
        // 步骤1：校验权益合法性
        SysStudentBenefit benefit = validateBenefit(benefitId);
        int needExp = benefit.getNeedExp() != null ? benefit.getNeedExp() : 0;

        // 步骤2：校验用户段位与经验
        SysStudentRank userRank = validateUserRank(userId);
        int currentExp = userRank.getCurrentExp() != null ? userRank.getCurrentExp() : 0;
        int expDeficit = needExp - currentExp;

        // 记录兑换前的段位信息
        String beforeRank = userRank.getRankLevel() + userRank.getRankSubLevel();
        String beforeRankLevel = userRank.getRankLevel();

        // 步骤3：经验不足时处理降级
        if (currentExp < needExp) {
            if (needDowngrade == null || !needDowngrade) {
                throw new ServiceException(String.format(
                        "经验值不足，兑换需%d经验，当前仅%d经验",
                        needExp, currentExp
                ));
            }
            handleDowngrade(userRank, expDeficit);
            currentExp = userRank.getCurrentExp();
        }

        // 步骤4：扣减兑换所需经验
        userRank.setCurrentExp(currentExp - needExp);
        int updateExpRows = rankMapper.updateStudentRankExp(userRank);
        if (updateExpRows != 1) {
            throw new ServiceException("经验值扣减失败，请重试");
        }

        // 步骤5：检查段位是否变化，若变化则记录历史并同步统计
        String afterRank = userRank.getRankLevel() + userRank.getRankSubLevel();
        String afterRankLevel = userRank.getRankLevel();
        if (!beforeRank.equals(afterRank)) {
            String changeType = determineChangeType(beforeRankLevel, afterRankLevel);
            recordRankHistory(userId, beforeRank, afterRank, changeType,
                    "兑换权益：" + benefit.getBenefitName());
        }

        // 步骤6：新增兑换记录
        addExchangeRecord(userId, benefit, needExp);

        return true;
    }


    /**
     * 获取用户兑换历史
     */
    @Override
    public List<SysStudentBenefitExchange> getUserExchangeHistory(Long userId) {
        if (userId == null || userId <= 0) {
            throw new ServiceException("用户ID不合法");
        }
        List<SysStudentBenefitExchange> history = exchangeMapper.selectExchangeByUserId(userId);
        return history != null ? history : new ArrayList<>();
    }


    /**
     * 获取用户段位变化统计
     */
    @Override
    public List<Map<String, Object>> getUserRankChangeStatistics(Long userId) {
        if (userId == null || userId <= 0) {
            throw new ServiceException("用户ID不合法");
        }
        return sysStudentRankHistoryMapper.countRankChangeByUserId(userId);
    }


    // ------------------------------ 私有工具方法 ------------------------------

    /**
     * 校验权益合法性
     */
    private SysStudentBenefit validateBenefit(Long benefitId) {
        if (benefitId == null || benefitId <= 0) {
            throw new ServiceException("权益ID不合法");
        }
        SysStudentBenefit benefit = benefitMapper.selectBenefitById(benefitId);
        if (benefit == null) {
            throw new ServiceException("该权益不存在或已禁用");
        }
        if (benefit.getNeedExp() == null || benefit.getNeedExp() <= 0) {
            throw new ServiceException("权益所需经验值配置异常");
        }
        return benefit;
    }


    /**
     * 校验用户段位信息
     */
    private SysStudentRank validateUserRank(Long userId) {
        if (userId == null || userId <= 0) {
            throw new ServiceException("用户ID不合法");
        }
        SysStudentRank userRank = rankMapper.selectRankByUserId(userId);
        if (userRank == null) {
            throw new ServiceException("用户段位信息未初始化，请联系管理员");
        }
        if (userRank.getRankLevel() == null || userRank.getRankSubLevel() == null) {
            throw new ServiceException("用户段位配置不完整，无法兑换");
        }
        return userRank;
    }


    /**
     * 处理段位降级
     */
    private void handleDowngrade(SysStudentRank userRank, int expDeficit) {
        if (LOWEST_RANK_LEVEL.equals(userRank.getRankLevel())) {
            throw new ServiceException("当前已为最低段位（倔强青铜），无法通过降级兑换");
        }

        int totalDowngradeTimes = (expDeficit + EXP_PER_SUB_DOWNGRADE - 1) / EXP_PER_SUB_DOWNGRADE;
        Integer originalNeedExp = userRank.getNeedExp();

        String currentTotalRank = userRank.getRankLevel();
        int currentRankIndex = RANK_LEVEL_ORDER.indexOf(currentTotalRank);
        if (currentRankIndex == -1) {
            throw new ServiceException("当前段位配置异常，无法降级");
        }

        for (int i = 0; i < totalDowngradeTimes; i++) {
            String currentSubRank = userRank.getRankSubLevel();
            int subRankIndex = RANK_SUB_LEVEL_ORDER.indexOf(currentSubRank);

            if (subRankIndex < RANK_SUB_LEVEL_ORDER.size() - 1) {
                userRank.setRankSubLevel(RANK_SUB_LEVEL_ORDER.get(subRankIndex + 1));
            } else {
                int newRankIndex = currentRankIndex - 1;
                if (newRankIndex < 0) {
                    throw new ServiceException(String.format(
                            "需降级%d次，但剩余段位不足，无法满足经验需求",
                            totalDowngradeTimes
                    ));
                }
                String newTotalRank = RANK_LEVEL_ORDER.get(newRankIndex);
                userRank.setRankLevel(newTotalRank);
                userRank.setRankSubLevel("I");
                currentRankIndex = newRankIndex;
            }

            int currentExp = userRank.getCurrentExp() == null ? 0 : userRank.getCurrentExp();
            userRank.setCurrentExp(currentExp + EXP_PER_SUB_DOWNGRADE);
        }

        userRank.setNeedExp(originalNeedExp);

        int updateRows = rankMapper.updateStudentRank(userRank);
        if (updateRows != 1) {
            throw new ServiceException("段位降级失败，请重试");
        }
    }


    /**
     * 新增兑换记录
     */
    private void addExchangeRecord(Long userId, SysStudentBenefit benefit, int needExp) {
        SysStudentBenefitExchange exchange = new SysStudentBenefitExchange();
        exchange.setUserId(userId);
        exchange.setBenefitId(benefit.getId());
        exchange.setBenefitName(benefit.getBenefitName());
        exchange.setCostExp(needExp);
        exchange.setExchangeTime(new Date());
        exchange.setStatus(1); // 1=已兑换
        int insertRows = exchangeMapper.insertExchangeRecord(exchange);
        if (insertRows != 1) {
            throw new ServiceException("兑换记录保存失败，请重试");
        }
    }


    /**
     * 记录段位变化历史
     */
    private void recordRankHistory(Long userId, String beforeRank, String afterRank,
                                   String changeType, String reason) {
        SysStudentRankHistory history = new SysStudentRankHistory();
        history.setUserId(userId);
        history.setBeforeRank(beforeRank);
        history.setAfterRank(afterRank);
        history.setChangeType(changeType);
        history.setReason(reason);

        int insertRows = sysStudentRankHistoryMapper.insert(history);
        if (insertRows != 1) {
            throw new ServiceException("段位历史记录保存失败");
        }
    }


    /**
     * 判断段位变化类型（升段/降段）
     */
    private String determineChangeType(String beforeRankLevel, String afterRankLevel) {
        int beforeIndex = RANK_LEVEL_ORDER.indexOf(beforeRankLevel);
        int afterIndex = RANK_LEVEL_ORDER.indexOf(afterRankLevel);

        if (beforeIndex == -1 || afterIndex == -1) {
            return "未知";
        }

        return afterIndex > beforeIndex ? "升段" : "降段";
    }
}
